/*------------------------------------------ ??? ---------------------------------------------*/
#include 	"CRC.h"
#include 	"xmodem.h"
#include	"define.h"
#include 	<stdio.h>
#include  "Uart.h"
#include  "math.h"
#include  "SPI.h"
int revflag =0;
extern int last_error;  
extern uint32 USART_RX_CNT;
extern uint8 xbuff[133];
uint32 readSize;

void out_buff(unsigned char *buff, int size)  
{  
    int arg = 0;  
		for(uint32 i=0; i<size; i++)
		{
				port_outbyte(*buff);
				buff++;
		}
}  
uint32 readSize;
uint32 in_buff(unsigned char *buff, int time_out)  
{ 	
		readSize = 0;
		//Timer0_Init(time_out);//ms
		last_error = 0;
		Irq1_Handler(buff);
	  if(readSize == 0)  
      last_error = 1;  
    return (readSize);  
}  

unsigned short calcrc(const unsigned char *ptr, int count)  
{  
    unsigned short crc;  
    char i;  
  
    crc = 0;  
    while (--count >= 0)  
    {  
        crc = crc ^ (int) *ptr++ << 8;  
        i = 8;  
        do  
        {  
            if (crc & 0x8000)  
                crc = crc << 1 ^ 0x1021;  
            else  
                crc = crc << 1;  
        } while (--i);  
    }  
  
    return (crc);  
} 

//recv_buff_size == 384  
int xmodemReceive(unsigned char *dest, int destsz)  
{    
    unsigned char xbuff[140];  
    int bufsz = 0;  
    int crc = 0;  
    unsigned char trychar = 'C';  
    unsigned char packetno = 1;  
    int c = 0;  
    int len = 0;  
    int retry = 0;  
    int retrans = MAXRETRANS;  
    int recvSize = 0;  
  
    for(;;)   
    {  
        for(retry = 0; retry < 16; retry ++)  
        {  
            if(trychar)  
            {  
                xbuff[0] = trychar;  
                out_buff(xbuff, 1);  
            }  
              
            recvSize = in_buff(xbuff, 2000);  
            c = xbuff[0];  
              
            if (last_error == 0)   
            {  
                switch(c)  
                {  
                    case SOH:  
                        bufsz = 128;  
                        goto start_recv;  
                    case STX:  
  
                    {  
                        xbuff[0] = CAN;  
                        out_buff(xbuff, 1);  
                    }  
                    return -1;  
                    case EOT:  
  
                        {  
                            xbuff[0] = ACK;  
                            out_buff(xbuff, 1);  
                        }  
                        return len;  
                    case CAN:  
  
                        in_buff(xbuff, DLY_1S);  
                        c = xbuff[0];  
                        if(c == CAN)  
                        {  
                            {  
                                xbuff[0] = ACK;  
                                out_buff(xbuff, 1);  
                            }  
                            return -1;  
                        }  
                        break;  
                    default:  
                        break;  
                }  
            }  
        }  
  
//        if (trychar == 'C')  
//        {  
//            trychar = NAK;  
//            continue;  
//        }  
  
        {  
//            xbuff[0] = CAN;  
//            out_buff(xbuff, 1);  
//            out_buff(xbuff, 1);  
//            out_buff(xbuff, 1);  
        }  
  
        return -2;  
  
start_recv:  
        if(trychar == 'C')  
            crc = 1;  
  
        trychar = 0;  
  
        if(recvSize != (bufsz + (crc ? 1 : 0) + 4))  
            goto reject;  
          
        if(xbuff[1] == (unsigned char)(~xbuff[2]) &&   
            (xbuff[1] == packetno || xbuff[1] == (unsigned char)packetno - 1) &&   
            check(crc, &xbuff[3], bufsz))  
        {  
            if(xbuff[1] == packetno)  
            {  
                int count = destsz - len;  
                  
                if (count > bufsz)  
                    count = bufsz;  
  
                if (count > 0)  
                {  
                    memcpy(&dest[len], &xbuff[3], count);  
                    len += count;  
                }  
  
                packetno ++;  
  
                retrans = MAXRETRANS+1;  
            }  
  
            if(-- retrans <= 0)  
            {  
                {  
                    xbuff[0] = CAN;  
                    out_buff(xbuff, 1);  
                    out_buff(xbuff, 1);  
                    out_buff(xbuff, 1);  
                }  
                return -3;  
            }  
  
            {  
                    xbuff[0] = ACK;  
                    out_buff(xbuff, 1);  
            }  
              
            continue;  
        }  
  
reject:    
        {  
                xbuff[0] = NAK;  
                out_buff(xbuff, 1);  
        }  
  
    }  
}  
  
//send_buff_size == 140  
int xmodemTransmit(unsigned char *src, int srcsz)  
{  
		DSP->dsp_rsv1 = 1;
    int bufsz = 0;  
    int crc = -1;  
    unsigned char packetno = 1;  
    int i = 0;  
    int c = 0;  
    int len = 0;  
    int retry = 0;  
		
    for(;;)  
    {  
        for( retry = 0; retry < 16; ++retry)  
        {  
						//receive first byte
					  delay_us(100);
            c = xbuff[0];
						DSP->dsp_rsv1 = 2;
						USART_RX_CNT = 0; 	
											
            if(last_error == 0)  
            {  
                switch(c)  
                {  
                    case 'C':  
                        crc = 1;  
												DSP->dsp_rsv1 = 3;
                        goto start_trans;  
												
                    case NAK:  
                        crc = 0;  
                        goto start_trans;  
                    case CAN:  
                        in_buff(xbuff, DLY_1S);  
                        c = xbuff[0];  
                        if(c == CAN)   
                        {  
                            {  
                                    xbuff[0] = ACK;  
                                    out_buff(xbuff, 1);  
                            }  
                            return -1;  
                        }  
                        break;  
                    default:  
                        break;  
                }  
            }  
        }  
        return -2;  
  
        for(;;)  
        {  
start_trans: 
						DSP->dsp_rsv1 = 4;
            xbuff[0] = SOH;       //start of hander 
            bufsz = 128;  	
            xbuff[1] = packetno;  //packet number
            xbuff[2] = ~packetno; //~ packet number
              
            c = srcsz - len;      //remaining bytes
            if(c > bufsz)  				//
                c = bufsz;  
  
            if(c >= 0)    
            {  
                memset(&xbuff[3], 0, bufsz);  
  
                if (c == 0)  
                {  
                    xbuff[3] = CTRLZ;  
                }  
                else  
                {  
                    memcpy(&xbuff[3], &src[len], c);  
                      
                    if (c < bufsz)//Fill in CTRZ if it is not enough 133 bytes
												for(int i=0; i<(bufsz-c-3); i++)
												{
													xbuff[3 + c+i] = CTRLZ;		
												}
                }  
                  
                if(crc)  
                {  
                    unsigned short ccrc = calcrc(&xbuff[3], bufsz);  
                      
                    xbuff[bufsz + 3] = (ccrc>>8) & 0xFF;  
                    xbuff[bufsz + 4] = ccrc & 0xFF;   
                }  
                else  
                {  
                    unsigned char ccks = 0;  
                      
                    for(i = 3; i < bufsz + 3; i ++)  
                    {  
                        ccks += xbuff[i];  
                    }  
                      
                    xbuff[bufsz + 3] = ccks;  
                }  
                  
                for(retry = 0; retry < MAXRETRANS; retry ++)  
                {  
                    out_buff(xbuff, bufsz + 4 + (crc ? 1 : 0));
										last_error =1;									
                    delay_us(100000);
										c = xbuff[0];
										USART_RX_CNT = 0; 	
                      
                    if(last_error == 0)  
                    {  
                        switch(c)  
                        {  
                            case ACK:  
                                packetno ++;  
                                len += bufsz;  
                                goto start_trans;  
                            case CAN:  
                                //in_buff(xbuff, DLY_1S);  
                                //c = xbuff[0];
																delay_us(10000);
																c = xbuff[0];
																USART_RX_CNT = 0; 														
                                if(c == CAN)  
                                {  
                                    {  
                                        xbuff[0] = ACK;  
                                        out_buff(xbuff, 1);  
                                    }  
                                      
                                    return -1;  
                                }  
                                break;  
                            case NAK:  
                                break;  
                            default:  
                                break;  
                        }  
                    }  
                }  
                return -4;  
            }  
            else  
            {  
                for(retry = 0; retry < 10; retry ++)  
                {  
                    {  
                        xbuff[0] = EOT;  
                        out_buff(xbuff, 1);  
                    }  
                      
                    //in_buff(xbuff, (DLY_1S)<<1); 
										delay_us(100000);
										c = xbuff[0];
										USART_RX_CNT = 0;  
  
                    if(c == ACK)  
                        break;  
                }  
              
                return ((c == ACK) ? len : -5);  
            }  
        }  
    }  
}












